//
// Created by Administrator on 2024/12/28.
//

#include "DataStream.h"


DataStream::DataStream():_pos(0)
{
    _byteOrder = getByteOrder();
}

DataStream::~DataStream()
{

}

void DataStream::reserve(int len)
{
    int size = _buffer.size();
    int cap = _buffer.capacity();
    //缓冲区容量不足，及时扩容
    if(size + len > cap)
    {
        while(size + len > cap)
        {
            if(cap == 0)
            {
                cap = 1;
            }
            else
            {
                cap *= 2;
            }
        }
        //容量改变
        _buffer.reserve(cap);
    }
}

void DataStream::write(const char *data, int len)
{
    //容量扩充
    reserve(len);
    //必须要扩大当前缓冲区的大小，否则无法memcpy
    int size = _buffer.size();
    _buffer.resize(size + len);
    std::memcpy(&_buffer[size],data,len);
}

void DataStream::write(bool value)
{
    char type = DataType::BOOL;
    write((char*)&type,sizeof(char));
    write((char*)&value,sizeof(bool));
}

void DataStream::write(char value)
{
    char type = DataType::CHAR;
    write((char*)&type,sizeof(char));
    write((char*)&value,sizeof(char));
}

void DataStream::write(int16_t value)
{
    char type = DataType::INT16;
    write((char *)&type,sizeof(char));
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(int16_t);
        //翻转字节序
        std::reverse(first,last);
    }
    write((char *)&value,sizeof(int16_t));
}

void DataStream::write(int32_t value)
{
    char type = DataType::INT32;
    write((char *)&type,sizeof(char));
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(int32_t);
        //翻转字节序
        std::reverse(first,last);
    }
    write((char*)&value,sizeof(int32_t));
}

void DataStream::write(int64_t value)
{
    char type = DataType::INT64;
    write((char *)&type,sizeof(char));
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(int64_t);
        //翻转字节序
        std::reverse(first,last);
    }
    write((char*)&value,sizeof(int64_t));
}

void DataStream::write(float value)
{
    char type = DataType::FLOAT;
    write((char *)&type,sizeof(char));
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(float);
        //翻转字节序
        std::reverse(first,last);
    }
    write((char*)&value,sizeof(float));
}

void DataStream::write(double value)
{
    char type = DataType::DOUBLE;
    write((char *)&type,sizeof(char));
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(double);
        //翻转字节序
        std::reverse(first,last);
    }
    write((char*)&value,sizeof(double));
}

void DataStream::write(const char *value)
{
    char type = DataType::STRING;
    write((char *)&type,sizeof(char));
    int len = strlen(value);
    write(len);
    write(value,len);
}

void DataStream::write(const std::string &value)
{
    char type = DataType::STRING;
    write((char *)&type,sizeof(char));
    int len = value.size();
    write(len);
    write(value.c_str(),len);
}

int DataStream::size() const
{
    return _buffer.size();
}

void DataStream::show()
{
    int size = _buffer.size();
    std::cout<<"size:"<<size<<std::endl;
    int i=0;
    while(i<size)
    {
        //第一个字节存放的为类型
        switch ((DataType)_buffer[i])
        {
            case DataType::BOOL:
                if((int)_buffer[++i] == 0)
                {
                    std::cout<<"false"<<std::endl;
                }
                else
                {
                    std::cout<<"true"<<std::endl;
                }
                ++i;
                break;
            case DataType::CHAR:
                std::cout<<_buffer[++i]<<std::endl;
                ++i;
                break;
            case DataType::INT16:
                std::cout<<*((int16_t*)&(_buffer[++i]))<<std::endl;
                i+=2;
                break;
            case DataType::INT32:
                std::cout<<*((int32_t *)&(_buffer[++i]))<<std::endl;
                i+=4;
                break;
            case DataType::INT64:
                std::cout<<*((int64_t *)&(_buffer[++i]))<<std::endl;
                i+=8;
                break;
            case DataType::FLOAT:
                std::cout<<*((float *)&(_buffer[++i]))<<std::endl;
                i+=4;
                break;
            case DataType::DOUBLE:
                std::cout<<*((double *)&(_buffer[++i]))<<std::endl;
                i+=8;
                break;
            case DataType::STRING:
                if((DataType)_buffer[++i] == DataType::INT32)
                {
                    int len = *((int32_t*)&(_buffer[++i]));
                    i+=4;
                    std::cout<<std::string(&_buffer[i],len);
                }
                else
                {
                    throw std::runtime_error("parse string error");
                }
                break;
            default:
                break;
        }
    }
}

DataStream &DataStream::operator<<(bool value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(char value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(int16_t value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(int32_t value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(int64_t value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(float value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(double value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(const char *value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator<<(const std::string &value)
{
    write(value);
    return *this;
}

bool DataStream::read(bool &value)
{
    if(_buffer[_pos] != DataType::BOOL)
    {
        return false;
    }
    _pos++;
    value = _buffer[_pos];
    _pos++;
    return true;
}

bool DataStream::read(char &value)
{
    if(_buffer[_pos] != DataType::CHAR)
    {
        return false;
    }
    _pos++;
    value = _buffer[_pos];
    _pos++;
    return true;
}

bool DataStream::read(int16_t &value)
{
    if(_buffer[_pos] != DataType::INT16)
    {
        return false;
    }
    _pos++;
    value = *reinterpret_cast<int16_t *>(&_buffer[_pos]);
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(int16_t);
        std::reverse(first,last);
    }
    _pos += 2;
    return true;
}

bool DataStream::read(int32_t &value)
{
    if(_buffer[_pos] != DataType::INT32)
    {
        return false;
    }
    _pos++;
    value = *reinterpret_cast<int32_t *>(&_buffer[_pos]);
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(int32_t);
        std::reverse(first,last);
    }
    _pos += 4;
    return true;
}

bool DataStream::read(int64_t &value)
{
    if(_buffer[_pos] != DataType::INT64)
    {
        return false;
    }
    _pos++;
    value = *reinterpret_cast<int64_t *>(&_buffer[_pos]);
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(int64_t);
        std::reverse(first,last);
    }
    _pos += 8;
    return true;
}

bool DataStream::read(float &value)
{
    if(_buffer[_pos] != DataType::FLOAT)
    {
        return false;
    }
    _pos++;
    value = *reinterpret_cast<float *>(&_buffer[_pos]);
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(float);
        std::reverse(first,last);
    }
    _pos += 4;
    return true;
}

bool DataStream::read(double &value)
{
    if(_buffer[_pos] != DataType::DOUBLE)
    {
        return false;
    }
    _pos++;
    value = *reinterpret_cast<double *>(&_buffer[_pos]);
    if(_byteOrder == ByteOrder::BigEndian)
    {
        char *first = (char *)&value;
        char *last = first + sizeof(double);
        std::reverse(first,last);
    }
    _pos += 8;
    return true;
}

bool DataStream::read(std::string &value)
{
    if(_buffer[_pos] != DataType::STRING)
    {
        return false;
    }
    _pos++;
    int len;
    read(len);
    if(len < 0)
    {
        std::runtime_error("string is empty");
        return false;
    }
    value.assign(reinterpret_cast<char*>(&_buffer[_pos]),len);
    _pos += len;
    return true;
}

DataStream &DataStream::operator>>(bool &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(char &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(int16_t &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(int32_t &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(int64_t &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(float &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(double &value)
{
    read(value);
    return *this;
}

DataStream &DataStream::operator>>(std::string &value)
{
    read(value);
    return *this;
}

bool DataStream::readType(char *type, int len)
{
    std::memcpy(type,(char *)&_buffer[_pos],len);
    _pos += len;
    return true;
}

void DataStream::write(const Serializable &value)
{
    value.serialize(*this);
}

bool DataStream::read(Serializable &value)
{
    value.unserialize(*this);
    return true;
}

DataStream &DataStream::operator<<(const Serializable &value)
{
    write(value);
    return *this;
}

DataStream &DataStream::operator>>(Serializable &value)
{
    read(value);
    return *this;
}

void DataStream::write_args()
{

}

bool DataStream::read_args()
{
    return true;
}

DataStream::ByteOrder DataStream::getByteOrder()
{
    int n = 0x12345678;
    char str[4];
    memcpy(str,&n,sizeof(int));
    if(str[0] == 0x12)
    {
        std::cout<<"BigEndian"<<"\n";
        return ByteOrder::BigEndian;
    }
    std::cout<<"LittleEndian"<<"\n";
    return ByteOrder::LittleEndian;
}

char *DataStream::data()
{
    return _buffer.data();
}




































